package com.zu.commu.local.threads;

import com.zu.commu.context.ServerContext;
import org.apache.log4j.Logger;

import java.nio.channels.SocketChannel;
import java.util.ArrayList;

public class LocalReadThreadManager {
	private static ArrayList<LocalReadThread> freeThreads;
	private static ArrayList<LocalReadThread> busiThreads;
	private static int maxThreadNum;
	private static int currThreadNum;
	private static int threadNum = 0;

	private static Object synObj = new Object();
	private static LocalReadThreadManager obj;

	public static LocalReadThreadManager instance() {
		if (obj == null) {
			obj = new LocalReadThreadManager();
		}
		return obj;
	}

	private LocalReadThreadManager() {
		busiThreads = new ArrayList<LocalReadThread>();
		freeThreads = new ArrayList<LocalReadThread>();
		maxThreadNum = ServerContext.maxThreadNumLocal;
		currThreadNum = 0;

		for (int i = 0; i < ServerContext.minThreadNumLocal; i++) {
			LocalReadThread t = new LocalReadThread(threadNum++);
			t.start();
			freeThreads.add(t);
			currThreadNum += 1;
		}
	}

	public void readSocketChannel(SocketChannel channel) {
		synchronized (synObj) {
			if (freeThreads.size() == 0) {
				if (currThreadNum < maxThreadNum) {
					LocalReadThread t = new LocalReadThread(threadNum++);
					t.start();
					busiThreads.add(t);
					currThreadNum += 1;

					t.setReadSocketChannel(channel);
				} else {
					do {
						try {
							synObj.wait();
						} catch (Exception e) {
							Logger log = Logger
									.getLogger("com.automic.commu.local.threads.LocalReadThreadManager");
							log.error("等待返回读socket的线程时发生等待异常!", e);
						}
						LocalReadThread t = (LocalReadThread) freeThreads
								.get(0);
						if (t == null)
							continue;
						freeThreads.remove(0);
						busiThreads.add(t);

						t.setReadSocketChannel(channel);
						break;
					} while (freeThreads.size() == 0);
				}

			} else {
				LocalReadThread t = (LocalReadThread) freeThreads.get(0);
				freeThreads.remove(0);
				busiThreads.add(t);
				t.setReadSocketChannel(channel);
			}
		}
	}

	public void freeThread(int threadNum, LocalReadThread t) {
		synchronized (synObj) {
			busiThreads.remove(t);
			freeThreads.add(t);
			synObj.notify();
		}
	}
}